home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / drivers1.zip / IBMTOKEN.ASM < prev    next >
Assembly Source File  |  1992-01-06  |  59KB  |  2,065 lines

  1. ;*****************************************************************************;
  2. ;*                                                                           *;
  3. ;*     File:   IBMTOKEN.ASM                                                  *;
  4. ;*     Auth:   Brian Fisher                                                  *;
  5. ;*             Queens University                                             *;
  6. ;*             Computing and Communications Services                         *;
  7. ;*             Rm 2-50 Dupuis Hall                                           *;
  8. ;*             Kingston Ontario                                              *;
  9. ;*                                                                           *;
  10. ;*     Date:   September 3 1989                                              *;
  11. ;*                                                                           *;
  12. ;*     Purp:   Ethernet (3C501) packet driver for IBM Token Ring.  This      *;
  13. ;*             driver uses the IBM LAN support program DIR interface.        *;
  14. ;*             The current implementation supports IP and ARP.               *;
  15. ;*                                                                           *;
  16. ;*             (C) 1989 Queens University                                    *;
  17. ;*             Computing and Communications Services.  This portion of       *;
  18. ;*             the program remains the property of Queens University.        *;
  19. ;*                                                                           *;
  20. ;*===========================================================================*;
  21. ;*     Program Logic:                                                        *;
  22. ;*                                                                           *;
  23. ;*     IBMTOKEN extracts IP and ARP data from ethernet datagrams passed to   *;
  24. ;*     it by the ULP, makes any adjustments required, then builds a token    *;
  25. ;*     ring datagram and sends it out over the network.  The process is      *;
  26. ;*     reversed when packets are received.  IBMTOKEN supports token ring     *;
  27. ;*     source routing and functions in a bridged environment.                *;
  28. ;*                                                                           *;
  29. ;*     The ULP uses Ethernet 'Blue Book' encapsulation.  IBMTOKEN uses       *;
  30. ;*     802.2 LLC format for transmission on token ring.  The IBM (tm)        *;
  31. ;*     LAN Support Program is required.  IBMTOKEN uses the DIR interface     *;
  32. ;*     to send/receive packets on token ring.                                *;
  33. ;*                                                                           *;
  34. ;*     IP packets do not require any modifications, and are sent 'as is.'    *;
  35. ;*     ARP packets have an 'hwr' field that must be changed fro 1h to 6h     *;
  36. ;*     during send_pkt, and changed back to 1h from 6h during _receive.      *;
  37. ;*                                                                           *;
  38. ;*     The minimum size of an ethernet packet is 60 bytes (minus the 4 byte  *;
  39. ;*     ethernet checksum).  Token ring has no lower limit.  The ULP will     *;
  40. ;*     reject 'short' packets, so IBMTOKEN lies and tells it there are 60    *;
  41. ;*     bytes.                                                                *;
  42. ;*                                                                           *;
  43. ;*     ARP packets are 28 bytes in length.  The ULP rounds the size of a     *;
  44. ;*     packet up to 60 bytes, so there is extra data on the end of the ARP   *;
  45. ;*     packet.  IBMTOKEN trims this off, because token ring hosts reject     *;
  46. ;*     'too long' ARP packets.                                               *;
  47. ;*                                                                           *;
  48. ;*     The minimum size of an ethernet packet is 60 bytes.  The maximum      *;
  49. ;*     is 1514 bytes.  The buffer sizes for token ring send/receive are      *;
  50. ;*     set to accomodate this.                                               *;
  51. ;*                                                                           *;
  52. ;*     Source Routing:                                                       *;
  53. ;*                                                                           *;
  54. ;*     The ethernet entrenched logic of the ULP does not accomodate source   *;
  55. ;*     routing.  IBMTOKEN provides a mechanism for source routing that is    *;
  56. ;*     transparent to the ULP.  The RIF information associated with token    *;
  57. ;*     ring source addresses are placed in a cache.  When the ULP sends to   *;
  58. ;*     that address, the RIF information is extracted from the cache and     *;
  59. ;*     used to route the packet to the target host.                          *;
  60. ;*                                                                           *;
  61. ;*     RIF Cache Logic:                                                      *;
  62. ;*                                                                           *;
  63. ;*        The cache logic uses an LRU algorithm.  Each entry is time         *;
  64. ;*        stamped.  If all the slots in the cache are being used, the oldest *;
  65. ;*        entry (assumed to be the LRU) is replaced (bumped from the cache). *;
  66. ;*                                                                           *;
  67. ;*        If the ULP uses an address whose RIF has been bumped from the      *;
  68. ;*        cache, a mechanism exists to rediscover the source route.          *;
  69. ;*        IBMTOKEN attaches a phony RIF, with the broadcast bit set and      *;
  70. ;*        and empty route table.  This packet travels to all rings.  When    *;
  71. ;*        the foreign host responds, the RIF info is placed back in the      *;
  72. ;*        cache.  Subsequent transmissions will use the rediscovered RIF.    *;
  73. ;*                                                                           *;
  74. ;*        The size of the RIF cache should be set to handle the maximum      *;
  75. ;*        number of concurrent hosts.  This will minimize the bumping        *;
  76. ;*        effect and minimize all rings broadcasts.                          *;
  77. ;*                                                                           *;
  78. ;*        I chose this algorithm so the ULP would not require any special    *;
  79. ;*        coding to work.  It eliminates the need for special syncronization *;
  80. ;*        of the ARP and RIF cache's.                                        *;
  81. ;*                                                                           *;
  82. ;*===========================================================================*;
  83. ;*                                                                           *;
  84. ;*      Revs:  Sep 29 1989     Successful tests with TN3270, FTP, and FTPBIN.*;
  85. ;*             B. Fisher       Some fine tuning required.                    *;
  86. ;*                                                                           *;
  87. ;*             Oct 1  1989     Cleaning up code.  Found bug that prevented   *;
  88. ;*                             buffer1/buffer2..n copies from working.       *;
  89. ;*                                                                           *;
  90. ;*             Oct 15 1989     Rearranged buffer sizes to accomodate Adapt I *;
  91. ;*                                                                           *;
  92. ;*             Nov 15 1989     Added missing popf at end of recv_complt      *;
  93. ;*                             Fixed missing popf at end of recv_complt      *;
  94. ;*                                                                           *;
  95. ;*             Nov 19 1989     Added marker to show interrupt activity       *;
  96. ;*                             for debugging.                                *;
  97. ;*                                                                           *;
  98. ;*             Nov 20 1989     Add changes for Release 5 compatibility       *;
  99. ;*                                                                           *;
  100. ;*             Nov 21 1989     Fix es/bx reversal at get_size                *;
  101. ;*                                                                           *;
  102. ;*             Nov 22 1989     RIF not working because of confusion with     *;
  103. ;*                             SA bit acquired via ARP and SA bit acquired   *;
  104. ;*                             through Token Receive.  Send_Pkt now looks    *;
  105. ;*                             up all dest addresses in RIF table.           *;
  106. ;*                                                                           *;
  107. ;*             Nov 23 1989     Have DEBUG mode report RIF table address when *;
  108. ;*                             get_multicast_ call made.                     *;
  109. ;*                                                                           *;
  110. ;*             Nov 28 1989     Add phony RIF to 'local' addresses so the     *;
  111. ;*                             bridge will pass them on.  ARP acquired HW    *;
  112. ;*                             addresses need RIF to cross bridge.  This is  *;
  113. ;*                             done in send_pkt.                             *;
  114. ;*                                                                           *;
  115. ;*             Nov 29 1989     Fixed REPT macro in SA_blk so size of SA info *;
  116. ;*                             is correct.  Didn't hurt function, however.   *;
  117. ;*                                                                           *;
  118. ;*             Nov 29 1989     Clear broadcast bit in RIF before entry in    *;
  119. ;*                             table.  This prevents bridges from altering   *;
  120. ;*                             existing route.  FF,FF,FF,FF,FF,FF address    *;
  121. ;*                             uses broadcast bit so ARP will work.          *;
  122. ;*                                                                           *;
  123. ;*             Nov 29 1989     Predefined broadcast RIF entry direction bit  *;
  124. ;*                             polarity reversal prevented broadcast from    *;
  125. ;*                             going over the bridge.                        *;
  126. ;*                                                                           *;
  127. ;*             Version 1.A -   Production Version released at Queens         *;
  128. ;*                                                                           *;
  129. ;*             Jan 02 1990     Fix missing CLD in _receiver, shows up when   *;
  130. ;*                             TOKREUI is used instead of Lan Support Pgm... *;
  131. ;*                                                                           *;
  132. ;*             Version 1.B                                                   *;
  133. ;*             Jan 15 1990     Begin modifications for LRU algorithm in the  *;
  134. ;*             (alpha 0)       RIF cache.  3rd parm on cmd line sets number  *;
  135. ;*                             of entries in the cache, which is allocated   *;
  136. ;*                             using INT 21, Function 48h.  The cache        *;
  137. ;*                             routines are modified to handle the new addr  *;
  138. ;*                             mode for accessing the table.                 *;
  139. ;*                                                                           *;
  140. ;*             Jan 16 1990     Adding time mark info to SA_table structure.  *;
  141. ;*             (alpha 1)       add_entry initializes t_mark                  *;
  142. ;*                             loc_entry refreshes t_mark when match found   *;
  143. ;*                             add_entry uses LRU slot in table when slots   *;
  144. ;*                             are all in use.                               *;
  145. ;*                                                                           *;
  146. ;*             Jan 18 1990     Updated the program documentation to reflect  *;
  147. ;*                             the operation of the RIF cache.               *;
  148. ;*                                                                           *;
  149. ;*             Version 1.C     Add code for compatibility with Release 6 of  *;
  150. ;*             Mar 18 1990     Clarkson drivers, including TERMINATE call.   *;
  151. ;*                                                                           *;
  152. ;*             Version 1.D     Fix bug that prevents get_address from        *;
  153. ;*                             returning adapter 1's hardware address.       *;
  154. ;*                                                                           *;
  155. ;*                                         *;
  156. ;*           Version 1.F     Modified to coexist with other LAN software   *;
  157. ;*           25.06.1991      (MS LAN Manager, IBM LAN Support ....) by     *;
  158. ;*                             Antero Koskinen, Nokia Data Systems Oy,       *;
  159. ;*                             Finland (anterok@xerver.data.nokia.fi)        *;
  160. ;*****************************************************************************;
  161.  
  162. version        equ    15h        ; Version F = 15h
  163.  
  164.     include    defs.asm
  165.  
  166. debug        =    0        ; set 1 for IRM marks on RX
  167.  
  168. alpha        =    0        ; ALPHA Test Version = 0
  169. alpha_ver    =    1        ; Which ALPHA Version...
  170.  
  171. hrs24        =    1573040        ; ticks in 24 hour day
  172.  
  173. toke_vect    =    5Ch        ; LAN Support Pgm Vector
  174. toke_wait    =    0FFh        ; completion code wait status
  175. pool_size    =    512        ; 8K space for buffer pool area
  176.  
  177. num_rcv_buff    =    2        ; <2 defaults to 8
  178. recv_size    =    1536        ; max size of card recieve buffer
  179. tran_size    =    1536        ; max size of transmit buffer
  180.  
  181. STATION_ID    =    0        ;                            ; talk using direct station
  182.  
  183. RECV_OPTIONS    =    0C0h        ; contiguous mac/data in bufs
  184.  
  185. open_cmd    =    3h        ; LAN Support OpCodes
  186. interrupt_cmd    =    0h
  187. initialize_cmd    =    20h
  188. close_cmd    =    4h
  189. modify_cmd    =    1h
  190. restore_cmd    =    2h
  191. trans_dir_cmd    =    0Ah
  192. free_ccb_cmd    =    27h
  193. recv_can_cmd    =    29h
  194. open_recv_cmd    =    28h
  195. get_status_cmd    =    21h
  196.  
  197. SA_table_size    =    32        ; default size of the RIF cache
  198. SA_min_size    =    2        ; minimum size
  199. SA_max_size    =    1024        ; maximum size
  200.  
  201. LLC_AC        =    10h        ; access control LLC
  202. LLC_FC        =    40h        ; frame control  LLC
  203. LLC_SSAP_DSAP    =    0AAAAh        ; reversed for network <grin>
  204. LLC_CON        =    03h
  205.  
  206. MAC_hdr_size    =    22        ; MAC+LLC+SNAP header length
  207.  
  208. not_SA_mask    =    7Fh
  209. SA_mask        =    80h
  210. RIF_size_mask    =    1Fh
  211. RIF_dir_bit    =    80h
  212.  
  213. broadcast_byte    =    0FFh        ; broadcast is FF,FF,FF,FF,FF,FF
  214.  
  215. ARP_type    =    0608h        ; reversed for network order
  216. ARP_Eth_hwr    =    0100h        ; reversed for network order
  217. ARP_Tok_hwr    =    0600h        ; reversed for network order
  218.     ARP_packet_size=    28    ; fixes Ethernet assumption...
  219. phony_RIF    =    2082h        ; used for bridges...
  220.  
  221.  
  222.  
  223. LLC_info_size    =    8        ; LLC (3) + SNAP(5) = 8
  224.  
  225. mark        =    0F90h        ; marker debug pos on screen 25
  226.  
  227. marker    macro   st,nd
  228.  
  229.     IF    debug NE 0        ; do marker if debug <> 0
  230.  
  231.     pushf                ; show 2 char marker on
  232.     push    es            ; 25th line, 1st column
  233.     push    ax
  234.     mov    ax,0B800h
  235.     mov    es,ax
  236.     mov    al,'&st&'
  237.     mov    byte ptr es:[mark],al
  238.     mov    al,byte ptr es:[mark+1]    ; get color value
  239.     inc    al
  240.     and    al,0Fh
  241.     or    al,1
  242.     mov    byte ptr es:[mark+1],al    ; advance it to show activity
  243.     mov    al,'&nd'
  244.     mov    byte ptr es:[mark+2],al
  245.     mov    al,byte ptr es:[mark+3]
  246.     inc    al
  247.     and    al,0Fh
  248.     or    al,1
  249.     mov    byte ptr es:[mark+3],al
  250.     pop    ax
  251.     pop    es
  252.     popf
  253.  
  254.     ENDIF
  255.  
  256.     endm
  257.  
  258. call_token    macro   ccb
  259. ;--------------------------------------;
  260. ; loads address of CCB in ES:BX, then  ;
  261. ; calls the Token Ring Interface.      ;
  262. ;--------------------------------------;
  263.     mov    ax,cs
  264.     mov    es,ax
  265.     mov    bx,offset &ccb&
  266.     int    toke_vect
  267.     endm
  268.  
  269.  
  270. call_wait    macro
  271.     local    wait_loop
  272. ;---------------------------------------;
  273. ; assumes ES:BX points to a CCB.  Waits ;
  274. ; for a pending command to terminate.   ;
  275. ;---------------------------------------;
  276. wait_loop:
  277.     mov    al,es:[bx+2]
  278.     cmp    al,toke_wait
  279.     je    wait_loop
  280.     endm
  281.  
  282.  
  283. ticks    macro
  284. ;---------------------------------------;
  285. ; get system timer ticks in CX:DX       ;
  286. ;---------------------------------------;
  287.     mov    ah,0
  288.     int    1Ah
  289.     endm
  290.  
  291.  
  292. set_ptr    macro   dest,addr
  293. ;---------------------------------------;
  294. ; loads a far pointer with a near       ;
  295. ; address offset and CS:                ;
  296. ;---------------------------------------;
  297.     mov    ax,offset &addr&
  298.     mov    word ptr [&dest&],ax
  299.     mov    ax,cs
  300.     mov    word ptr [&dest&+2],ax
  301.     endm
  302.  
  303.  
  304. print$    macro   string
  305. ;---------------------------------------;
  306. ;  sends $ terminated string to screen  ;
  307. ;---------------------------------------;
  308.     mov    ah,9
  309.     mov    dx,offset &string&    ; print $ terminated string
  310.     int    21h
  311.     endm
  312.  
  313.  
  314. clr_struc    macro   name
  315. ;---------------------------------------;
  316. ;  clear all bytes of the named struc   ;
  317. ;  to zero.  Useful for Token calls.    ;
  318. ;---------------------------------------;
  319.     mov    cx,SIZE &name&        ; uses ax, es:di, cx
  320.     mov    ax,ds
  321.     mov    es,ax
  322.     mov    di,offset &name&
  323.     xor    al,al
  324.     cld
  325.     rep    stosb            ; set all elements to 0
  326.     endm
  327.  
  328.  
  329. rdupb    macro   l,n
  330. &l&        db    ?
  331.     rept    &n&-1
  332.     db    ?
  333.     endm
  334.     endm
  335.  
  336. ccb_blk    struc                ; CCB used for local token ring calls.
  337. adapter        db    ?        ; adapter 0 or 1
  338. command        db    ?        ; command code
  339. returncode    db    ?        ; command completion code
  340. work        db    ?        ; scratch
  341. pointer        dd    ?        ; queue pointer
  342. complt        dd    ?        ; command complete appendage
  343. parms        dd    ?        ; pointer to CCB parameter table
  344. ccb_blk    ends
  345.  
  346.  
  347. init_parms    struc            ; parameters for DIR_INITIALIZE
  348. bring_ups    dw    ?        ; result of bring up tests
  349. sram_addr    dw    ?        ; shared ram address
  350. reserved    dd    ?        ; not used...
  351. chk_exit    dd    ?        ; adapter check exit
  352. status        dd    ?        ; ring status exit
  353. error        dd    ?        ; PC error exit
  354. init_parms    ends
  355.  
  356.  
  357. o_parms    struc                ; ccb parms for DIR_OPEN
  358. adapt        dd    ?        ; ptr to adapter parms
  359. direct        dd    ?        ; ptr to direct parms
  360. dlc        dd    ?        ; ptr to dlc parms
  361. msg        dd    ?        ; ptr to msg parms
  362. o_parms    ends
  363.  
  364.  
  365. ada_blk    struc                ; adapter open parms table format
  366. err_code    dw    ?        ; open errors detected
  367. options        dw    ?        ; various options
  368. node_addr    dd    ?        ; node address ( 4 bytes here +  )
  369.     dw    ?            ; rest of node address ( 2 here  )
  370. group_add    dd    ?        ; group address
  371. func_add    dd    ?        ; functional address
  372. rcv_buff    dw    ?        ; number of receive buffers
  373. rcv_len        dw    ?        ; receive buffer length
  374. dhb_len        dw    ?        ; length of transmit buffers
  375. hold_buf    db    ?        ; number of tx buffers
  376.     db    ?            ; reserved
  377. lock_code    dw    ?        ; lock code
  378. id_addr        dd    ?        ; address of id code
  379. ada_blk    ends
  380.  
  381.  
  382. dir_blk    struc                ; dir interfce open parms table format
  383. buf_size    dw    ?        ; size of direct station buffer
  384. pool_blks    dw    ?        ; number of 16 byte blocks in buff pool
  385. pool_addr    dd    ?        ; address of direct station buffer pool
  386. chk_exit    dd    ?        ; the rest can be 0 (defaults) for now
  387. stat_exit    dd    ?        ; ring status appendage pointer
  388. err_exit    dd    ?        ; PC error exit
  389. work_addr    dd    ?        ; work area segment value
  390. len_req        dw    ?        ; work area length requested
  391. len_act        dw    ?        ; actual length obtained
  392. dir_blk    ends
  393.  
  394.  
  395. dlc_blk    struc                ; dlc interface open parms table format
  396. max_sap        db    ?        ; max number of saps
  397. max_sta        db    ?        ; max number of stations
  398. max_gsap    db    ?        ; max group saps
  399. max_gmem    db    ?        ; max members per group
  400. t1_tick1    db    ?        ; DLC timer t1 interval
  401. t2_tick1    db    ?        ; DLC timer t2 interval
  402. TI_tick1    db    ?        ; DLC timer TI interval
  403. t1_tick2    db    ?        ; DLC timer t1 group 2
  404. t2_tick2    db    ?        ; DLC timer t2 group 2
  405. TI_tick2    db    ?        ; DLC timer TI group 2
  406. dlc_blk    ends
  407.  
  408.  
  409. mod_blk    struc                ; modify open parms parameter block
  410. buf_size    dw    ?        ; size of SAP buffers
  411. pool_blks    dw    ?        ; length in 16-byte, of buffer pool
  412. pool_adrs    dd    ?        ; address of direct interface buf pool
  413. chkt_exit    dd    ?        ; appendage, adapter check
  414. stat_exit    dd    ?        ; appendage, ring status
  415. err_exit    dd    ?        ; appendage, PC error exit
  416. new_opts    dw    ?        ; new options (wrap is ignored)
  417. mod_blk    ends
  418.  
  419.  
  420. tx_blk    struc                ; transmit.dir.frame parameter block
  421. station        dw    ?        ; defines station sending data
  422. trans_fs    db    ?        ; * stripped FS field (returned)
  423. rsap        db    ?        ; RSAP (remote sap value)
  424. queue_1        dd    ?        ; address of TX queue 1
  425. queue_2        dd    ?        ; address of TX queue 2
  426. buf_len_1    dw    ?        ; length of buffer 1
  427. buf_len_2    dw    ?        ; length of buffer 2
  428. buffer_1    dd    ?        ; address of the first transmit buffer
  429. buffer_2    dd    ?        ; address of the second transmit buffer
  430. tx_blk    ends
  431.  
  432.  
  433. free_blk    struc            ; buffer.free parameters
  434. st_id        dw    ?        ; station id
  435. buf_left    dw    ?        ; returns number of buffers left
  436. resrvd        dd    ?        ;
  437. first_buf    dd    ?        ; address of 1st buffer to free
  438. free_blk    ends
  439.  
  440.  
  441. get_blk    struc                ; buffer.get parameters
  442. stn_id        dw    ?        ; station id
  443. buffr_lef    dw    ?        ; buffers left
  444. buff_get    db    ?        ; number of buffers to get
  445. resrv1        db    ?        ; 3 bytes not used
  446. resrv2        db    ?
  447. resrv3        db    ?
  448. frst_buff    dd    ?        ; address of buffer obtained
  449. get_blk    ends
  450.  
  451.  
  452. rx_blk    struc                ; receive parms
  453. id        dw    ?        ; station id
  454. user_len    dw    ?        ; size of user space in buffer
  455. receiver    dd    ?        ; appendage for received data
  456. first_bf    dd    ?        ; pointer to 1st buffer
  457. opts        db    ?        ; receive options
  458. rx_blk    ends
  459.  
  460.  
  461. status_blk    struc            ; parameter table for dir.status
  462. encoded_addr    dw    ?        ; adapters permanent ring address
  463.     dd    ?
  464. node_adrs    dw    ?        ; ring address set by open
  465.     dd    ?
  466. group_adrs    dd    ?
  467. func_adrs    dd    ?
  468.     REPT    16
  469.     db    ?
  470.     ENDM
  471.     REPT    3
  472.     dd    ?
  473.     ENDM
  474.     dw    ?
  475. status_blk    ends
  476.  
  477.  
  478.  
  479.  
  480.  
  481. mac_header    struc            ; token ring mac header format
  482. AC        db    ?        ; access control byte
  483. FC        db    ?        ; frame control byte
  484.     rdupb    dest,EADDR_LEN
  485.     rdupb    source,EADDR_LEN
  486. dsap        db    ?        ; LLC dsap
  487. ssap        db    ?        ; LLC ssap
  488. control        db    ?        ; control byte
  489. ptype        db    ?
  490.     db    ?            ; SNAP header
  491.     db    ?
  492. ethtype        dw    ?        ; EtherType
  493. rif        dw    ?        ; optional RIF information
  494.     REPT    8            ; segment information
  495.     dw    ?            ; this is not its real position.
  496.     ENDM                ; this is a variable length field...
  497. mac_header    ends
  498.  
  499.  
  500. SA_blk    struc
  501.     rdupb    s_addr,EADDR_LEN
  502. RCF        db    ?
  503.     db    ?
  504. route        dw    ?
  505.     REPT    7
  506.     dw    ?
  507.     ENDM    ?
  508. t_mark        dd    ?        ; LRU time marker...
  509. SA_blk    ends
  510.  
  511.  
  512. ether_hdr    struc            ; ethernet header format
  513.     rdupb    ether_dest,EADDR_LEN
  514.     rdupb    ether_src,EADDR_LEN
  515. ether_type    dw    ?
  516. ether_hdr    ends
  517.  
  518.  
  519. first_buffer    struc            ; Token receive 1st buffer
  520. next_buffer    dd    ?        ; ptr to next buffer
  521. xx1        dw    ?
  522. data_size    dw    ?        ; size of user data
  523.     REPT    12
  524.     db    ?
  525.     ENDM
  526. user_data    db    ?
  527. first_buffer    ends
  528.  
  529. user_data2    =    12        ; 2nd buffer slightly different
  530.  
  531.  
  532.  
  533. ;=============================================================================;
  534. ;======================= START OF PROGRAM CODE ===============================;
  535. ;=============================================================================;
  536.  
  537. code    segment word public
  538.     assume    cs:code, ds:code
  539.  
  540. Token_address    db    EADDR_LEN dup (0)    ; holds my address after init.
  541.  
  542. ccb        ccb_blk <>        ; scratch CCB
  543. free_ccb    ccb_blk <>
  544. tx_parms    tx_blk  <>        ; transmit.dir.frame parms
  545. iparms        init_parms <>        ; init parms
  546. pool_buff    db    (pool_size+1)*16 dup (?); buffer pool
  547. free_parms    free_blk <>        ; buffer.free parameters
  548. get_parms    get_blk  <>        ; buffer.get parameters
  549.  
  550. rx_ccb        ccb_blk <>        ; receive CCB
  551. rx_parms    rx_blk  <>        ; receive parms
  552.  
  553.  
  554. id_code        db    18 dup (0)    ; phony product id code
  555.                     ; (a real space saver...)
  556.  
  557. my_open        db    0        ; set to 1 if we opened the adapter
  558.  
  559. ada_parm    ada_blk <0,0,0,0,0,0,num_rcv_buff,recv_size,tran_size,1,0,0,0>
  560.  
  561. dir_parm    dir_blk <0,pool_size,0,0,0,0,0,0,0>
  562. dlc_parm    dlc_blk <0,0,0,0,0,0,0,0,0,0>
  563. init_parm    o_parms <0,0,0,0>
  564. initccb        ccb_blk <0,0,0,0,0,0,0>
  565. toke_status    status_blk <>
  566.  
  567. modparms    mod_blk <0,pool_size,0,0,0,0,0>
  568. modccb        ccb_blk < 0,modify_cmd,0,0,0,0,0>
  569.  
  570. lan_header    mac_header  <LLC_AC,LLC_FC>
  571.  
  572.  
  573. ;      SA RIF table has 1 entry in it by default, for the broadcast address.
  574. ;
  575. SA_index    dw    1
  576. SA_size        dw    SA_table_size    ; size of table
  577.         dw    0        ; parsed from cmd line
  578.  
  579. SA_delta    dw    0        ; delta t for LRU find
  580.         dw    0
  581. SA_ord        dw    0        ; ordinal for LRU entry
  582.  
  583. memory_needed    dw    0        ; scratch for memory calculation
  584.  
  585.  
  586. dir_interrupt    proc
  587. ;---------------------------------------;
  588. ; Entry: token_card (0 or 1)            ;
  589. ;  Exit: AX = CCB return code           ;
  590. ;---------------------------------------;
  591.     clr_struc    ccb        ; initialize CCB
  592.     mov    ax,token_card
  593.     mov    [ccb.adapter],al
  594.     mov    al,interrupt_cmd
  595.     mov    [ccb.command],al
  596.     call_token    ccb        ; call the interface
  597.     call_wait    ccb        ; wait for completion
  598.     xor    ah,ah
  599.     mov    al,[ccb.returncode]    ; return the result in AX
  600.     ret
  601. dir_interrupt    endp
  602.  
  603.  
  604. dir_initialize    proc
  605. ;---------------------------------------;
  606. ; Entry: token_card (0 or 1)            ;
  607. ;  Exit:                                ;
  608. ;       Ah = bring up return code       ;
  609. ;       Al = ccb return code            ;
  610. ;---------------------------------------;
  611.     clr_struc    ccb        ; clear ccb
  612.     clr_struc    iparms        ; clear init parms (defaults)
  613.  
  614.     mov    ax,token_card        ; assign parameters
  615.     mov    [ccb.adapter],al
  616.     mov    al,initialize_cmd    ; command....
  617.     mov    [ccb.command],al
  618.  
  619.     set_ptr    ccb.parms,iparms    ; link to init parms
  620.  
  621.     call_token    ccb        ; call the interface
  622.     call_wait    ccb        ; wait for completion
  623.  
  624.     mov    ah,byte ptr iparms.bring_ups
  625.     mov    al,[ccb.returncode]
  626.  
  627.     ret
  628. dir_initialize    endp
  629.  
  630.  
  631. dir_open_adapter    proc
  632. ;---------------------------------------;
  633. ; Entry: token_card (0 or 1)            ;
  634. ;  Exit: AX = CCB return code           ;
  635. ;---------------------------------------;
  636.     mov    ax,token_card        ; get adapter number
  637.     mov    [initccb.adapter],al
  638.  
  639.     mov    al,open_cmd
  640.     mov    [initccb.command],al    ; 03h open_adapter command
  641.  
  642.     set_ptr    ada_parm.id_addr,id_code
  643.     set_ptr    dir_parm.pool_addr,pool_buff
  644.     set_ptr    init_parm.adapt,ada_parm
  645.     set_ptr    init_parm.direct,dir_parm
  646.     set_ptr    init_parm.dlc,dlc_parm
  647.     set_ptr    initccb.parms,init_parm
  648.  
  649.     xor    al,al
  650.     mov    [initccb.returncode],al
  651.  
  652.     call_token    initccb        ; call the interface
  653.     call_wait    initccb        ; wait for completion
  654.  
  655.     xor    ah,ah
  656.     mov    al,[initccb.returncode]
  657.  
  658.     ret
  659. dir_open_adapter    endp
  660.  
  661.  
  662. dir_close_adapter    proc
  663. ;---------------------------------------;
  664. ; Entry: token_card (0 or 1)            ;
  665. ;  Exit: AX = CCB return code           ;
  666. ;---------------------------------------;
  667.     clr_struc    ccb        ; clear CCB
  668.  
  669.     mov    ax,token_card        ; initialize local CCB
  670.     mov    [ccb.adapter],al
  671.     mov    al,close_cmd        ; close command
  672.     mov    [ccb.command],al
  673.  
  674.     call_token    ccb        ; call the interface
  675.     call_wait    ccb        ; wait for completion
  676.  
  677.     xor    ah,ah
  678.     mov    al,[ccb.returncode]    ; return the result
  679.     ret
  680. dir_close_adapter    endp
  681.  
  682.  
  683. dir_modify_open    proc
  684. ;---------------------------------------;
  685. ; Entry: token_card (0 or 1)            ;
  686. ;  Exit: AX = CCB return code           ;
  687. ;---------------------------------------;
  688.     mov    ax,token_card        ; get adapter number
  689.     mov    [modccb.adapter],al    ; command is a constant in ccb
  690.  
  691.     set_ptr    modparms.pool_adrs,pool_buff
  692.     set_ptr    modccb.parms,modparms
  693.  
  694.     xor    al,al
  695.     mov    [modccb.returncode],al
  696.  
  697.     call_token    modccb        ; call the interface
  698.     call_wait    modccb        ; wait for completion
  699.  
  700.     xor    ah,ah
  701.     mov    al,[modccb.returncode]
  702.     ret
  703. dir_modify_open    endp
  704.  
  705.  
  706. dir_restore_open    proc
  707. ;---------------------------------------;
  708. ; Entry: token_card (0 or 1)            ;
  709. ;  Exit: AX = CCB return code           ;
  710. ;---------------------------------------;
  711.     clr_struc    ccb        ; initialize CCB
  712.  
  713.     mov    ax,token_card
  714.     mov    [ccb.adapter],al
  715.     mov    al,restore_cmd        ; dir.restore.open.parms
  716.     mov    [ccb.command],al
  717.  
  718.     call_token    ccb        ; call the interface
  719.     call_wait    ccb        ; wait for completion
  720.  
  721.     xor    ah,ah
  722.     mov    al,[ccb.returncode]    ; return the result in AX
  723.     ret
  724. dir_restore_open    endp
  725.  
  726.  
  727. transmit_dir_frame    proc
  728. ;---------------------------------------;
  729. ; Entry: token_card (0 or 1)            ;
  730. ;                                       ;
  731. ; Stack:                                ;
  732. ;       sp+14  dw [usr seg]             ;
  733. ;       sp+12  dw [usr ofs]             ;
  734. ;       sp+10  dw [usrsize]             ;
  735. ;       sp+8   dw [hdr seg]             ;
  736. ;       sp+6   dw [hdr ofs]             ;
  737. ;       sp+4   dw [hdrsize]             ;
  738. ;       sp+2   dw [ret ofs]             ;
  739. ;       sp+0   dw [  bp   ]             ;
  740. ;                                       ;
  741. ;  Exit:                                ;
  742. ;       Ah = stripped FS field          ;
  743. ;       al = CCB return code            ;
  744. ;---------------------------------------;
  745.  
  746. trans_frame    struc            ; transmit_dir_frame parms
  747. _x_bp        dw    ?        ; old bp register
  748. _x_ret_ofs    dw    ?        ; near return address
  749. header_size    dw    ?        ; MAC header size
  750. llc_header    dd    ?        ; address of header
  751. user_dsize    dw    ?        ; user data size
  752. user_daddress    dd    ?        ; user data address
  753. trans_frame    ends
  754.  
  755.     push    bp
  756.     mov    bp,sp
  757.  
  758.     mov    ax,cs
  759.     mov    ds,ax
  760.  
  761.     clr_struc    ccb        ; zero the CCB
  762.     clr_struc    tx_parms    ; zero parameters
  763.  
  764.     mov    ax,token_card        ; initialize local CCB
  765.     mov    [ccb.adapter],al
  766.     mov    al,trans_dir_cmd    ; transmit.dir.frame
  767.     mov    [ccb.command],al
  768. ;
  769. ;      Set up transmit parameters, and link them to
  770. ;      the CCB...
  771. ;
  772.     mov    ax,offset tx_parms
  773.     mov    word ptr [ccb.parms],ax
  774.  
  775.     mov    ax,cs
  776.     mov    word ptr [ccb.parms+2],ax
  777. ;
  778.     mov    ax,STATION_ID
  779.  
  780.     mov    word ptr [tx_parms.station],ax
  781.  
  782.     mov    ax,[bp][user_dsize]
  783.     mov    word ptr [tx_parms.buf_len_2],ax
  784.  
  785.     mov    ax,word ptr [bp][user_daddress]
  786.     mov    word ptr [tx_parms.buffer_2],ax
  787.     mov    ax,word ptr [bp][user_daddress+2]
  788.     mov    word ptr [tx_parms.buffer_2+2],ax
  789.  
  790.     mov    ax,[bp][header_size]
  791.     mov    word ptr [tx_parms.buf_len_1],ax
  792.  
  793.     mov    ax,word ptr [bp][llc_header]
  794.     mov    word ptr [tx_parms.buffer_1],ax
  795.     mov    ax,word ptr [bp][llc_header+2]
  796.     mov    word ptr [tx_parms.buffer_1+2],ax
  797.  
  798.     call_token    ccb        ; call the interface
  799.     call_wait    ccb        ; wait for completion
  800.  
  801.     mov    ah,[tx_parms.trans_fs]
  802.     mov    al,[ccb.returncode]
  803.  
  804.     pop    bp
  805.  
  806.     ret    (SIZE trans_frame)-4    ; (forget bp and ret address)
  807. transmit_dir_frame    endp
  808.  
  809.  
  810. buffer_free    proc
  811. ;---------------------------------------;
  812. ; Entry:                                ;
  813. ;      sp+4    [ seg 1st buffer ]       ;
  814. ;      sp+2    [ ofs 1st buffer ]       ;
  815. ;      sp+0    [ bp             ]       ;
  816. ;                                       ;
  817. ;  Exit: AX = CCB return code           ;
  818. ;---------------------------------------;
  819.     mov    ax,cs
  820.     mov    ds,ax
  821.  
  822.     push    bp
  823.     mov    bp,sp
  824.  
  825.     clr_struc    free_ccb
  826.     clr_struc    free_parms
  827.  
  828.     mov    ax,token_card        ; initialize local CCB
  829.     mov    [free_ccb.adapter],al
  830.  
  831.     mov    al,free_ccb_cmd        ; buffer.free
  832.     mov    [free_ccb.command],al
  833.  
  834.     mov    ax,offset free_parms
  835.     mov    word ptr [free_ccb.parms],ax
  836.  
  837.     mov    ax,cs
  838.     mov    word ptr [free_ccb.parms+2],ax
  839. ;
  840. ;      Load free_parms to release buffer
  841. ;
  842.     mov    ax,STATION_ID
  843.     mov    word ptr [free_parms.st_id],ax
  844.  
  845.     mov    ax,word ptr [bp][4]
  846.     mov    word ptr [free_parms.first_buf],ax
  847.     mov    ax,word ptr [bp][6]
  848.     mov    word ptr [free_parms.first_buf+2],ax
  849.  
  850.     call_token    free_ccb    ; call the interface
  851.  
  852.     xor    ah,ah
  853.     mov    al,[free_ccb.returncode]; return the result in AX
  854.  
  855.     pop    bp
  856.  
  857.     ret    4
  858. buffer_free    endp
  859.  
  860.  
  861. recv_cancel    proc
  862. ;---------------------------------------;
  863. ; Entry: token_card (0 or 1)            ;
  864. ;                                       ;
  865. ;  Exit:                                ;
  866. ;       AX = CCB return code            ;
  867. ;                                       ;
  868. ;---------------------------------------;
  869.     mov    ax,token_card        ; initialize local CCB
  870.     mov    [ccb.adapter],al
  871.  
  872.     mov    al,recv_can_cmd        ; receive.cancel
  873.     mov    [ccb.command],al
  874.  
  875.     xor    ax,ax            ; word/bytes set to 0
  876.     mov    [ccb.returncode],al
  877.     mov    [ccb.work],al
  878.     mov    word ptr [ccb.pointer],ax
  879.     mov    word ptr [ccb.pointer+2],ax
  880.     mov    word ptr [ccb.complt],ax
  881.     mov    word ptr [ccb.complt+2],ax
  882.     mov    word ptr [ccb.parms+2],ax
  883.  
  884.     mov    ax,STATION_ID
  885.     mov    word ptr [ccb.parms],ax
  886.  
  887.     call_token    ccb        ; call the interface
  888.     call_wait    ccb        ; wait for completion
  889.  
  890.     xor    ah,ah
  891.     mov    al,[ccb.returncode]    ; return the result in AX
  892.     ret
  893.  
  894. recv_cancel    endp
  895.  
  896.  
  897. open_receive    proc
  898. ;---------------------------------------;
  899. ; Entry: token_card (0 or 1)            ;
  900. ;                                       ;
  901. ; Stack:                                ;
  902. ;       sp+6   dw [ret ofs]             ;
  903. ;       sp+4   dw [  bp   ]             ;
  904. ;       sp+2   dw [  ds   ]             ;
  905. ;       sp+0   dw [  es   ]             ;
  906. ;                                       ;
  907. ;  Exit:                                ;
  908. ;       AX = CCB return code            ;
  909. ;---------------------------------------;
  910.     mov    ax,cs
  911.     mov    ds,ax
  912.  
  913.     clr_struc    rx_ccb
  914.     clr_struc    rx_parms    ;
  915.  
  916.     mov    ax,token_card        ; initialize local CCB
  917.     mov    [rx_ccb.adapter],al
  918.  
  919.     mov    al,open_recv_cmd    ; receive
  920.     mov    [rx_ccb.command],al
  921.  
  922.     mov    ax,offset recv_complt
  923.     mov    word ptr [rx_ccb.complt],ax
  924.     mov    ax,cs
  925.     mov    word ptr [rx_ccb.complt+2],ax
  926. ;
  927. ;      Link receive parameters table
  928. ;
  929.     mov    ax,offset rx_parms
  930.     mov    word ptr [rx_ccb.parms],ax
  931.     mov    ax,cs
  932.     mov    word ptr [rx_ccb.parms+2],ax
  933.  
  934.     mov    ax,STATION_ID
  935.     mov    word ptr [rx_parms.id],ax
  936.  
  937.     mov    al,RECV_OPTIONS
  938.     mov    rx_parms.opts,al
  939.  
  940.     mov    ax,offset _receiver
  941.     mov    word ptr [rx_parms.receiver],ax
  942.     mov    ax,cs
  943.     mov    word ptr [rx_parms.receiver+2],ax
  944. ;
  945. ;       Note: The receive request is submitted, but it doesn't 'complete'
  946. ;             here.  So DON'T wait for a completion code!
  947. ;
  948.     call_token    rx_ccb        ; call the interface
  949.  
  950.     xor    ah,ah
  951.     mov    al,[rx_ccb.returncode]    ; return the result
  952.     ret
  953. open_receive    endp
  954.  
  955.  
  956. recv_complt    proc
  957. ;
  958. ;      This procedure is an interrupt routine called by the Token Card
  959. ;      when receive completion occurs after an error.  All it should have
  960. ;      to do is resubmit the receive request, then exit.
  961. ;
  962.     pushf
  963.     push    ax
  964.     push    bx
  965.     push    cx
  966.     push    dx
  967.     push    si
  968.     push    di
  969.     push    ds
  970.     push    es
  971.     push    bp
  972.     sti
  973.  
  974.     marker    E,R
  975.     call    open_receive        ; restart communications
  976.  
  977.     pop    bp
  978.     pop    es
  979.     pop    ds
  980.     pop    di
  981.     pop    si
  982.     pop    dx
  983.     pop    cx
  984.     pop    bx
  985.     pop    ax
  986.     popf
  987.     iret
  988. recv_complt    endp
  989.  
  990.  
  991. recv_frame    struc            ; stack frame for receiver
  992. RIF_size    dw    ?        ; size of RIF in packet.
  993. user_buff    dd    ?        ; pointer to users buffer
  994. user_size    dw    ?        ; size of buffer needed/used
  995. _BP        dw    ?        ; register set on stack
  996. _ES        dw    ?
  997. _DS        dw    ?
  998. _DI        dw    ?
  999. _SI        dw    ?
  1000. _DX        dw    ?
  1001. _CX        dw    ?
  1002. _BX        dw    ?
  1003. _AX        dw    ?
  1004. recv_frame    ends
  1005.  
  1006.  
  1007. _receiver    proc
  1008. ;
  1009. ;      This interrupt procedure is called when the Token Ring
  1010. ;      card has data.
  1011. ;
  1012. ;      On entry, ds:si points to the CCB
  1013. ;                es:bx points to the receive first_buffer in the chain.
  1014. ;
  1015. ;
  1016.     pushf                ; save CPU environment
  1017.     push    ax
  1018.     push    bx
  1019.     push    cx
  1020.     push    dx
  1021.     push    si
  1022.     push    di
  1023.     push    ds
  1024.     push    es
  1025.     push    bp
  1026.  
  1027.     push    ax            ; local variables: size of receive data
  1028.     push    ax            ; segment of user supplied buffer
  1029.     push    ax            ; offset of user supplied buffer
  1030.     push    ax
  1031.  
  1032.     mov    bp,sp            ; set stack frame reference
  1033.  
  1034.     sti                ; enable further int activity
  1035.  
  1036.     marker    R,X
  1037. ;
  1038. ;      If the source address is mine, ignore the transmission!
  1039. ;
  1040.     mov    ax,cs
  1041.     mov    ds,ax
  1042.     mov    si,offset Token_address
  1043.     mov    di,bx
  1044.     add    di,user_data+source    ; ds:si -> token address
  1045.                     ; es:di -> pkt
  1046.     mov    cx,EADDR_LEN
  1047.     push    word ptr es:[di]    ; save msb of address
  1048.  
  1049.     mov    al,es:[di]
  1050.     and    al,not_SA_mask        ; drop SA indicator
  1051.     mov    es:[di],al        ; fix the bit during compare
  1052. ;
  1053. ;      patch to fix direction bit problem...
  1054. ;
  1055.     cld
  1056.     repe    cmpsb            ; do string compare now
  1057.     jne    not_mine
  1058.  
  1059.     mov    di,bx
  1060.     add    di,user_data+source
  1061.     pop    word ptr es:[di]    ; restore token address
  1062.  
  1063.     jmp    drop_buffer        ; from me, ignore it!
  1064.  
  1065. ;      es:bx -> 1st receive buffer
  1066. not_mine:
  1067.     mov    di,bx
  1068.     add    di,user_data+source
  1069.     pop    word ptr es:[di]    ; save MSB of source address
  1070.  
  1071.     xor    ax,ax
  1072.     mov    cx,ax
  1073.     mov    word ptr [bp][RIF_size],ax; zero RIF size value
  1074.  
  1075. get_size:
  1076.     mov    ax,es
  1077.     or    ax,bx
  1078.     je    got_size
  1079.     add    cx,word ptr es:[bx][data_size]
  1080.     push    word ptr es:[bx][next_buffer]
  1081.     push    word ptr es:[bx][next_buffer+2]
  1082.     pop    es            ; ************************
  1083.     pop    bx            ; ************************
  1084.     jmp    get_size
  1085.  
  1086. got_size:
  1087.     sub    cx,LLC_info_size    ; adjust size for Token
  1088.  
  1089.     mov    ax,word ptr [bp][_ES]
  1090.     mov    es,ax
  1091.     mov    bx,word ptr [bp][_BX]    ; get buffer address
  1092.     mov    al,es:[bx][user_data+source]
  1093.     and    al,SA_mask        ; if SA, adjust total
  1094.     je    got_no_fix
  1095.  
  1096. ;
  1097. ;      How big is the RIF?
  1098. ;
  1099.     mov    ax,word ptr es:[bx][user_data+source+EADDR_LEN]
  1100.     and    ax,RIF_size_mask
  1101.     mov    word ptr [bp][RIF_size],ax
  1102. ;
  1103. ;      Take away size of RIF.  Upper level doesn't get it.
  1104. ;
  1105.     sub    cx,ax            ; subtract RIF size
  1106.  
  1107. got_no_fix:
  1108. ;
  1109. ;      Min Ethersize is RUNT, so check it first, round up if necessary
  1110. ;
  1111.     cmp    cx,RUNT
  1112.     jge    no_adjust_cx
  1113.     mov    cx,RUNT
  1114.  
  1115. no_adjust_cx:
  1116.     mov    word ptr [bp][user_size],cx; save size of receive data
  1117. ;
  1118. ;      Call recv_find to determine if the receiver wants the data,
  1119. ;      and where it should be stored.
  1120. ;
  1121.     mov    ax,word ptr [bp][_ES]    ; reload segment/offset
  1122.     mov    es,ax
  1123.     mov    di,word ptr [bp][_BX]    ; points to E-type in Token
  1124.     add    di,40            ; assumes Buffer 1 format,
  1125.     add    di,word ptr [bp][RIF_size]; RIF size added now...
  1126. ;
  1127. ;      if ARP type, convert hardware address space value back to Ethernet...
  1128. ;
  1129.     mov    ax,word ptr es:[di]    ;  -> EtherType in SNAP
  1130.     cmp    ax,ARP_type        ; ARP packet?
  1131.     jne    not_rx_arp
  1132.     mov    ax,ARP_Eth_hwr
  1133.     mov    word ptr es:[di][2],ax    ; fix 1st field of data
  1134.  
  1135. not_rx_arp:
  1136.     mov    dl,BLUEBOOK
  1137.     call    recv_find        ; es:di -> Snap E-Type, CX = data size
  1138.  
  1139.     mov    word ptr [bp][user_buff],di
  1140.     mov    ax,es
  1141.     mov    word ptr [bp][user_buff+2],ax
  1142.  
  1143.     or    ax,di
  1144.     jne    do_copy
  1145.     jmp    drop_buffer        ; if ptr is 0, doesn't want it!
  1146. ;
  1147. ;      Copy Token Ring data to users Ethernet format receive buffer.
  1148. ;
  1149. do_copy:
  1150. ;
  1151. ;      Since the upper level wants it, better keep the RIF info in case we
  1152. ;      want to send a return message.
  1153. ;
  1154.     mov    ax,word ptr [bp][_ES]
  1155.     mov    ds,ax
  1156.     mov    si,word ptr [bp][_BX]
  1157.     add    si,user_data+source    ; 1st byte of source address
  1158.     call    add_entry        ; do table maintenance
  1159. ;
  1160. ;      Copy data to the users buffer
  1161. ;
  1162.     mov    di,word ptr [bp][user_buff]; Ethernet destination buffer
  1163.     mov    ax,word ptr [bp][user_buff+2]
  1164.     mov    es,ax
  1165.  
  1166.     mov    si,word ptr [bp][_BX]    ; Token Ring Source buffer
  1167.     mov    bx,si
  1168.     mov    ax,word ptr [bp][_ES]
  1169.     mov    ds,ax
  1170.     add    si,user_data        ; offset to user data
  1171. ;
  1172. ;      ds:si points to 1st token buffer
  1173. ;      es:di points to ethernet format buffer
  1174.  
  1175. ;      1. Copy Token/Ether  dest/source field to users buffer
  1176. ;         after stripping off the SA bit in the source address.
  1177.  
  1178.     mov    al,byte ptr ds:[si+source];****************
  1179.     and    al,07Fh            ;***** NEW ******
  1180.     mov    byte ptr ds:[si+source],al;****************
  1181.  
  1182.     mov    cx,EADDR_LEN*2        ; 2 address fields
  1183.     add    si,2            ; offset to dest field
  1184.     cld
  1185.     rep    movsb
  1186.  
  1187.     add    si,LLC_info_size-2    ; assume no RIF,
  1188.     add    si,word ptr [bp][RIF_size]; compensate for RIF
  1189.  
  1190.     movsw                ; get ethertype
  1191.  
  1192.     mov    cx,[bx][data_size]    ; get length of data
  1193.     sub    cx,MAC_hdr_size        ; drop MAC header stuff
  1194.     sub    cx,[bp][RIF_size]    ; compensate for RIF
  1195.  
  1196. copy_buffer:
  1197.     cld
  1198.     rep    movsb            ; copy rest of data to Ether..
  1199.     push    word ptr [bx][next_buffer]
  1200.     push    word ptr [bx][next_buffer+2]
  1201.     pop    ds
  1202.     pop    si
  1203.     mov    bx,si            ; bx is base of buffer
  1204.     add    si,user_data2        ; si offsets to user data
  1205.     mov    cx,[bx][data_size]    ; length of user data
  1206.     mov    ax,ds
  1207.     or    ax,bx            ; NULL pointer?
  1208.     jne    copy_buffer        ; no, keep copying...
  1209. ;
  1210. ;      Tell Upper layer I copied the data into his buffer...
  1211. ;
  1212.     mov    si,word ptr [bp][user_buff]
  1213.     mov    ax,word ptr [bp][user_buff+2]
  1214.     mov    ds,ax
  1215.     mov    cx,word ptr [bp][user_size]
  1216.  
  1217.     call    recv_copy
  1218. ;
  1219. ;      _ES:_BX points to 1st receive buffer, drop it, then exit
  1220. ;
  1221. drop_buffer:
  1222.     mov    ax,word ptr [bp][_ES]    ; tell Token, drop buffer
  1223.     mov    bx,word ptr [bp][_BX]
  1224.     push    ax
  1225.     push    bx
  1226.     call    buffer_free        ; seg:offs of 1st buff on stack
  1227.  
  1228.     pop    ax            ; vacuum local variables off
  1229.     pop    ax            ; the stack
  1230.     pop    ax
  1231.     pop    ax
  1232.  
  1233.     pop    bp
  1234.     pop    es
  1235.     pop    ds
  1236.     pop    di
  1237.     pop    si
  1238.     pop    dx
  1239.     pop    cx
  1240.     pop    bx
  1241.     pop    ax
  1242.     popf
  1243.  
  1244.     marker    r,x
  1245.  
  1246.     iret
  1247.  
  1248. _receiver    endp
  1249.  
  1250.  
  1251. comp_adr    proc
  1252. ;
  1253. ;      Compare two token address values, set flags without affecting any
  1254. ;      other registers.  JE or JNE to test result.
  1255. ;
  1256.     push    si
  1257.     push    di
  1258.     push    cx
  1259.     cld
  1260.     mov    cx,EADDR_LEN
  1261.     repe    cmpsb
  1262.     pop    cx
  1263.     pop    di
  1264.     pop    si
  1265.     ret
  1266. comp_adr    endp
  1267.  
  1268.  
  1269. make_adr    proc
  1270. ;
  1271. ;      Given CX as an ordinal (1..n) into the RIF_cache, build the address
  1272. ;      in ES:DI
  1273. ;
  1274.     push    ax
  1275.     push    cx
  1276.     dec    cx
  1277.     xor    di,di
  1278.     cmp    cx,0
  1279.     je    make_adr1
  1280. make_adr0:
  1281.     add    di,SIZE SA_blk        ; build index into SA_table
  1282.     loop    make_adr0
  1283.  
  1284. make_adr1:
  1285.     mov    ax,cs            ; segment of table
  1286.     mov    es,ax
  1287.     add    di,offset RIF_cache    ; + offset to base of table
  1288.     pop    cx
  1289.     pop    ax
  1290.     ret
  1291. make_adr    endp
  1292.  
  1293.  
  1294.  
  1295. add_entry    proc
  1296. ;
  1297. ;      DS:SI -> Token Address, make an entry in the SA routing table
  1298. ;
  1299.     mov    cx,EADDR_LEN        ; don't add broadcasts to table
  1300.     push    si            ; leave the default intact
  1301.     cld
  1302.  
  1303. add_entry0:
  1304.     lodsb                ; Broadcast?
  1305.     cmp    al,broadcast_byte
  1306.     loope    add_entry0
  1307.     pop    si
  1308.     je    add_done        ; yes...
  1309.  
  1310.     mov    al,ds:[si]        ; is it a source route address?
  1311.     and    al,SA_mask
  1312.     je    add_done
  1313. ;
  1314. ;      Is it in the table?
  1315.  
  1316.     call    loc_entry
  1317.     jc    add_done        ; c = 1, its in the table.
  1318. ;
  1319. ;      if its not in the table, try to put it in a 'new' slot...
  1320. ;
  1321.     mov    cx,word ptr cs:[SA_index]
  1322.     cmp    cx,word ptr cs:[SA_size]
  1323.     jne    lotsa_room        ; room in table, make flat entry
  1324. ;
  1325. ;      If no new slots available, determine LRU entry and overwrite it...
  1326. ;
  1327.     push    ds            ; save initial pointer
  1328.     push    si
  1329.     call    find_lru        ; returns cx ordinal into table
  1330.     pop    si            ; restore initial pointer
  1331.     pop    ds
  1332.     jmp    do_entry
  1333. ;
  1334. ;      Update entry pointer, overwrite a new slot in the table...
  1335. ;
  1336. lotsa_room:
  1337.     inc    cx
  1338.     mov    word ptr cs:[SA_index],cx; advance the table index
  1339.  
  1340. ;      before entry is made, the broadcast bit must be cleared so bridges
  1341. ;      will leave the segment values alone.
  1342.  
  1343. do_entry:
  1344.     mov    al,byte ptr ds:[si+EADDR_LEN]
  1345.     and    al,07Fh            ; clear broadcast bit
  1346.     mov    byte ptr ds:[si+EADDR_LEN],al
  1347.  
  1348.     call    make_adr        ; build destination address
  1349.     push    si
  1350.     push    di
  1351.     push    es
  1352.     mov    cx,SIZE SA_blk
  1353.     cld
  1354.     rep    movsb            ; copy RIF into table
  1355.     pop    es
  1356.     pop    di
  1357.     pop    si
  1358. ;
  1359. ;      Put time stamp on the new entry for LRU algorithm
  1360. ;
  1361.     ticks                ; cx:dx = ticks count
  1362.     mov    word ptr es:[di+t_mark],dx
  1363.     mov    word ptr es:[di+t_mark+2],cx
  1364.  
  1365. add_done:
  1366.     ret
  1367. add_entry    endp
  1368.  
  1369.  
  1370. find_lru    proc
  1371. ;
  1372. ;      locates oldest entry in the RIF_cache, returns the ordinal number in
  1373. ;      CX.  The first entry is NEVER chosen because it contains the broadcast
  1374. ;      route predefined in the table!
  1375. ;
  1376. ;      CX = 2 .. cs:[SA_size]  ( range to be searched )
  1377. ;
  1378. ;      SA_delta  dword contains time difference for last one checked
  1379. ;      SA_ord    word  contains the ordinal of the least recently used
  1380. ;
  1381.     xor    ax,ax            ; zero search variables
  1382.     mov    word ptr cs:[SA_delta],ax
  1383.     mov    word ptr cs:[SA_delta+2],ax
  1384.     mov    word ptr cs:[SA_ord],ax
  1385.  
  1386.     mov    cx,2            ; 1st entry is NEVER touched!
  1387.  
  1388. find_loop:
  1389.     call    make_adr        ; es:di -> current entry
  1390.     push    cx            ; save index
  1391.     ticks                ; cx:dx = current ticks
  1392.     sub    cx,word ptr es:[di+t_mark+2]; ticks = mark
  1393.     sbb    dx,word ptr es:[di+t_mark]
  1394. ;
  1395. ;      if the result < 0, then ticks went past midnight.  Add 24 hrs in
  1396. ;      ticks to get the real delta t.
  1397. ;
  1398.     jge    _no_fix
  1399.     add    cx,((hrs24 shr 16) and 0ffffh); longint to fix delta t
  1400.     adc    dx,(hrs24 and 0ffffh)    ; add 24 hours in ticks to
  1401.  
  1402. _no_fix:
  1403. ;
  1404. ;      If the result is greater than the stored SA_delta, replace it with
  1405. ;      this entry, then continue the loop...
  1406. ;
  1407.     push    cx            ; save hi/low delta t result
  1408.     push    dx
  1409.     sub    cx,word ptr cs:[SA_delta+2]
  1410.     sbb    dx,word ptr cs:[SA_delta]
  1411.     jl    _no_replace
  1412.  
  1413. ;
  1414. ;      replace SA_ord and SA_delta with entry that has been around longer
  1415. ;
  1416.     pop    cs:[SA_delta]        ; pull lo/hi delta t result
  1417.     pop    cs:[SA_delta+2]
  1418.     pop    cx            ; get ordinal...
  1419.     mov    word ptr cs:[SA_ord],cx    ; replace SA_ord...
  1420.     jmp    _next_find
  1421.  
  1422. _no_replace:
  1423.     pop    cx
  1424.     pop    cx
  1425.     pop    cx
  1426.  
  1427. _next_find:
  1428.     inc    cx
  1429.     cmp    cx,word ptr cs:[SA_size]
  1430.     jle    find_loop
  1431.     jmp    _find_exit
  1432.  
  1433. _find_exit:
  1434.     mov    cx,SA_ord        ; return ordinal of LRU
  1435.     ret
  1436.  
  1437. find_lru    endp
  1438.  
  1439.  
  1440.  
  1441. loc_entry    proc
  1442. ;
  1443. ;      DS:SI -> Token Address, locate entry in the SA routing table
  1444. ;      ES:DI -> SA information in table, if carry is set.
  1445. ;
  1446.     mov    cx,word ptr cs:[SA_index]; any entries in table?
  1447.     cmp    cx,0
  1448.     je    loc_done
  1449.  
  1450.  
  1451. loc_entry0:
  1452.     call    make_adr        ; build address into table
  1453.     call    comp_adr        ; compare Token Addresses
  1454.     je    loc_found        ; if matches, in table
  1455.     loop    loc_entry0
  1456.  
  1457. loc_done:
  1458.     clc
  1459.     ret
  1460.  
  1461. loc_found:
  1462.                     ;    ES:DI points to matching entry
  1463.     ticks                ; cx:dx = ticks value for
  1464.     mov    word ptr es:[di+t_mark],dx; refresh of existing
  1465.     mov    word ptr es:[di+t_mark+2],cx; entry...
  1466.  
  1467.     stc
  1468.     ret
  1469.  
  1470. loc_entry    endp
  1471.  
  1472.  
  1473. ;==============================================================================
  1474. ;
  1475. ;=================== DRIVER CODE  =============================================
  1476. ;
  1477. ;==============================================================================
  1478. ;
  1479. ;
  1480. ;      Token Ring Card number, parsed from command line
  1481. ;
  1482. token_card    dw    0        ; default adapter number 0
  1483.     dw    0            ; this prevents type error.
  1484.  
  1485. toke_ad_name    db    "Adapter (0 or 1) ",'$'
  1486. toke_sa_name    db    " RIF Cache Size: ",'$'
  1487.  
  1488. dir_open_mode    db    0        ; set <> 0 if modify_open used
  1489. msg_initialize    db    " INIT: Initializing the adapter...",CR,LF,'$'
  1490. msg_opening    db    "       Opening the adapter...",CR,LF,'$'
  1491. msg_complete    db    "       IBMTOKEN - Initialization complete.",CR,LF,'$'
  1492. msg_modifying    db    "       Creating direct buffer pool...",CR,LF,'$'
  1493. msg_bad_adapter    db    "ERROR: adapter must be 0 or 1.",CR,LF,'$'
  1494. no_mem_cache    db    "ERROR: RIF_cache value out of range!",CR,LF
  1495. msg_bad_init    db    "ERROR: Initialization Failed.",CR,LF
  1496.     db    "       Installation aborted!",CR,LF,'$'
  1497. msg_receiving    db    "       Starting receiver process...",CR,LF,'$'
  1498.  
  1499.     public    int_no
  1500. int_no        db    0,0,0,0        ;must be four bytes long for get_number.
  1501.  
  1502.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  1503. driver_class    db    BLUEBOOK,0    ;from the packet spec
  1504. driver_type    db    1        ;from the packet spec
  1505. driver_name    db    'IBMTokenR',0    ;name of the driver.
  1506. driver_function    db    2
  1507.  
  1508. parameter_list    label   byte
  1509.     db    1            ;major rev of packet driver
  1510.     db    9            ;minor rev of packet driver
  1511.     db    14            ;length of parameter list
  1512.     db    EADDR_LEN        ;length of MAC-layer address
  1513.     dw    GIANT            ;MTU, including MAC headers
  1514.     dw    MAX_MULTICAST * EADDR_LEN;buffer size of multicast addrs
  1515.     dw    0            ;(# of back-to-back MTU rcvs) - 1
  1516.     dw    0            ;(# of successive xmits) - 1
  1517.     dw    0            ;Interrupt # to hook for post-EOI
  1518.                     ;processing, 0 == none,
  1519.  
  1520.     public    rcv_modes
  1521. rcv_modes    dw    4        ;number of receive modes in our table.
  1522.     dw    0,0,0,rcv_mode_3
  1523.  
  1524.  
  1525. sp_frame    struc
  1526. __bp        dw    ?
  1527. u_size        dw    ?
  1528. u_data        dd    ?
  1529. u_snap        dw    ?
  1530. sp_frame    ends
  1531.  
  1532.  
  1533.     public    as_send_pkt
  1534. ; The Asynchronous Transmit Packet routine.
  1535. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  1536. ;   interrupts possibly enabled.
  1537. ; Exit with nc if ok, or else cy if error, dh set to error number.
  1538. ;   es:di and interrupt enable flag preserved on exit.
  1539. as_send_pkt:
  1540.     ret
  1541.  
  1542.     public    drop_pkt
  1543. ; Drop a packet from the queue.
  1544. ; Enter with es:di -> iocb.
  1545. drop_pkt:
  1546.     assume    ds:nothing
  1547.     ret
  1548.  
  1549.     public    xmit
  1550. ; Process a transmit interrupt with the least possible latency to achieve
  1551. ;   back-to-back packet transmissions.
  1552. ; May only use ax and dx.
  1553. xmit:
  1554.     assume    ds:nothing
  1555.     ret
  1556.  
  1557.  
  1558.     public    send_pkt
  1559. send_pkt:
  1560. ;enter with ds:si -> packet, cx = packet length.
  1561. ;exit with nc if ok, or else cy if error, dh set to error number.
  1562.     assume    ds:nothing
  1563.     sti
  1564.     marker    T,X
  1565.  
  1566. ;
  1567. ;      construct local stack frame
  1568. ;
  1569.     mov    ax,word ptr ds:[si][ether_type]
  1570.     push    ax
  1571.     push    ds            ; pointer to user data packet
  1572.     mov    ax,si
  1573.     add    ax,SIZE ether_hdr
  1574.     push    ax            ; adjusted userdata pointer
  1575.     sub    cx,SIZE ether_hdr    ; adjust size for send
  1576.     push    cx
  1577.     push    bp
  1578.     mov    bp,sp            ; use sp_frame for reference
  1579.  
  1580.  
  1581.     mov    ax,cs            ; set dest pointer to LLC header
  1582.     mov    es,ax
  1583.  
  1584.     mov    di,offset lan_header.dest
  1585.     mov    cx,EADDR_LEN*2        ; copy dest|source fields
  1586.     cld
  1587.     rep    movsb
  1588. ;
  1589. ;      ds:si -> dest address, locate it in the SA RIF table
  1590. ;
  1591.     mov    ax,cs
  1592.     mov    ds,ax
  1593.     mov    si,offset lan_header.dest; building LAN header info here
  1594.  
  1595. ; Set bit 7 of address, force lookup in table.  If it is found, add RIF,
  1596. ; otherwise, assume the local net.
  1597.  
  1598.     mov    al,byte ptr ds:[si]
  1599.     or    al,080h
  1600.     mov    byte ptr ds:[si],al
  1601.  
  1602.     call    loc_entry
  1603.     jc    send_pkt1        ; yes, copy out RIF information
  1604. ;
  1605. ;      add the rest of the fields to the LLC header, and set the size
  1606. ;      for the transmit call.
  1607. ;
  1608.     mov    al,byte ptr ds:[si]    ; dest address 1st byte,
  1609.                     ; lop off SA bit
  1610.     and    al,not_SA_mask
  1611.     mov    byte ptr ds:[si],al
  1612.  
  1613.     mov    al,byte ptr ds:[si][EADDR_LEN]; force U bit high
  1614.     or    al,080h
  1615.     mov    byte ptr ds:[si][EADDR_LEN],al
  1616.  
  1617.     add    si,EADDR_LEN*2        ; point after dest/source addrs.
  1618.     mov    ax,es
  1619.     mov    bx,ds
  1620.     mov    ds,ax
  1621.     mov    es,bx
  1622.     xchg    si,di
  1623.  
  1624. ;      addresses acquired from ARP default to broadcast mode, using phony
  1625. ;      RIF info so the bridge will pass the packet along.
  1626. ;
  1627.     mov    ax,phony_RIF        ; copy phony RIF to LLC buffer,
  1628.     cld                ; so 'local' can cross bridge..
  1629.     stosw
  1630.     jmp    send_pkt2
  1631.  
  1632. send_pkt1:
  1633. ;
  1634. ;      source/dest address need to be adjusted for routing.
  1635. ;
  1636.     mov    cx,EADDR_LEN
  1637.     push    si
  1638.  
  1639. send_pkt3:
  1640.     mov    al,byte ptr ds:[si]
  1641.     inc    si
  1642.     cmp    al,broadcast_byte
  1643.     loope    send_pkt3
  1644.     pop    si
  1645.     je    send_pkt4        ; broadcast address?
  1646.  
  1647.  
  1648.     mov    al,byte ptr ds:[si]    ; dest, lop off SA bit
  1649.     and    al,not_SA_mask
  1650.     mov    byte ptr ds:[si],al
  1651.  
  1652. send_pkt4:
  1653.     mov    al,byte ptr ds:[si][EADDR_LEN]
  1654.     or    al,SA_mask        ; set SA bit for RIF
  1655.     mov    byte ptr ds:[si][EADDR_LEN],al
  1656.  
  1657.     add    si,EADDR_LEN*2        ; ds:si -> dest for RIF info.
  1658.     add    di,EADDR_LEN        ; es:di -> RIF info, addr fld
  1659.  
  1660.     mov    bx,si            ; keep RIF pos in LLC header
  1661.  
  1662.     mov    ax,word ptr es:[di]    ; get rif info
  1663.     and    ax,RIF_size_mask    ; get length of RIF
  1664.     mov    cx,ax
  1665.     mov    ax,es
  1666.     mov    dx,ds
  1667.     mov    ds,ax
  1668.     mov    es,dx
  1669.     xchg    si,di
  1670.     cld
  1671.     rep    movsb
  1672.  
  1673. ;
  1674. ;      Got RIF, fix direction bit.
  1675. ;
  1676.     mov    al,es:[bx][1]        ; RIF+1 = dir bit location
  1677.     xor    al,RIF_dir_bit        ; change direction
  1678.     mov    es:[bx][1],al
  1679.  
  1680. send_pkt2:
  1681. ;
  1682. ;      es:di -> target in LLC for the rest of the header,
  1683. ;      add LLC and SNAP information.
  1684. ;
  1685.     mov    ax,LLC_SSAP_DSAP    ; build LLC portion
  1686.     stosw
  1687.     mov    al,LLC_CON
  1688.     stosb
  1689.     xor    ax,ax            ; 3 bytes for Ptype in SNAP
  1690.     stosw
  1691.     stosb
  1692.     mov    ax,word ptr [bp][u_snap]
  1693.     stosw
  1694. ;
  1695. ;      header is complete.
  1696. ;
  1697.     sub    di,offset lan_header    ; calculate size of LLC header
  1698. ;
  1699. ;      stack parameters for Transmit
  1700. ;
  1701.     pop    bp
  1702.  
  1703.     mov    ax,cs
  1704.     mov    ds,ax            ; set ds for transmit entry
  1705.     push    ax
  1706.     mov    ax,offset lan_header
  1707.     push    ax
  1708.     push    di
  1709.  
  1710. ;--------------------------------------------------------------------
  1711. ;       If Users data is an ARP packet, 0806 type, then the 1st field
  1712. ;       must be changed from 0001 to 0006 for Token Ring broadcast, or
  1713. ;       no one will respond.  Funny, eh?  Another thing.  Since an ARP
  1714. ;       packet is smaller than the min size for Ethernet, the caller rounds
  1715. ;       up the size.  I have to change it back, or some Token hosts won't
  1716. ;       ARP for me.  The nerve!
  1717. ;
  1718.     push    bp
  1719.     mov    bp,sp
  1720.     mov    ax,word ptr [bp][14]    ; offset to ARP type on stack...
  1721.     pop    bp
  1722.  
  1723.     cmp    ax,ARP_type        ; network byte order is backwards
  1724.     jne    not_tx_arp
  1725. ;
  1726. ;      The first field of the ARP data has to be changed from 0001 to 0006
  1727. ;
  1728.     push    bp            ; use trans_frame
  1729.     push    bp            ; dummy entry on stack...
  1730.     mov    bp,sp
  1731.     mov    ax,word ptr [bp][user_daddress+2]; addr of user data
  1732.     mov    es,ax
  1733.     mov    di,word ptr [bp][user_daddress]
  1734.  
  1735.     mov    ax,ARP_Tok_hwr
  1736.     mov    word ptr es:[di],ax    ; change ARP type to 0006
  1737.  
  1738.     mov    ax,ARP_packet_size    ; 28  bytes in an ARP packet
  1739.     mov    word ptr [bp][user_dsize],ax; reset users data size
  1740.  
  1741.     pop    bp            ; pop fake return address
  1742.     pop    bp            ; pop real bp
  1743.  
  1744. not_tx_arp:
  1745.     call    transmit_dir_frame    ; send the packet
  1746.  
  1747.     pop    ax            ; vacuum
  1748.     clc
  1749.     ret
  1750.  
  1751.  
  1752.                public  get_address
  1753. get_address:
  1754. ;get the address of the interface.
  1755. ;enter with es:di -> place to get the address, cx = size of address buffer.
  1756. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  1757.     assume    ds:code
  1758. ;
  1759.     push    di
  1760.     push    es
  1761.     push    cx
  1762.  
  1763.     mov    ax,cs
  1764.     mov    ds,ax
  1765.     clr_struc ccb
  1766.     clr_struc toke_status
  1767.  
  1768.     mov    ax,token_card        ; set adapter number
  1769.     mov    [ccb.adapter],al
  1770.     mov    al,get_status_cmd    ; get status returns address
  1771.     mov    ccb.command,al
  1772.     mov    ax,offset toke_status
  1773.     mov    word ptr [ccb.parms],ax
  1774.     mov    ax,ds
  1775.     mov    word ptr [ccb.parms+2],ax
  1776.  
  1777.     call_token    ccb
  1778.     call_wait    ccb
  1779.  
  1780.     mov    si,offset toke_status.node_adrs
  1781.     pop    cx
  1782.     pop    es
  1783.     pop    di
  1784.     cmp    cx,EADDR_LEN        ; got the room for it?
  1785.     jb    get_address_fail
  1786.  
  1787.     cld
  1788.     mov    cx,EADDR_LEN
  1789.     rep    movsb
  1790.     mov    cx,EADDR_LEN
  1791.     clc
  1792.     ret
  1793.  
  1794. get_address_fail:
  1795.     stc
  1796.     ret
  1797.  
  1798.  
  1799.     public    set_address
  1800. set_address:
  1801. ;enter with ds:si -> Ethernet address, CX = length of address.
  1802. ;exit with nc if okay, or cy, dh=error if any errors.
  1803.     assume    ds:nothing
  1804.     clc
  1805.     ret
  1806.  
  1807.  
  1808. rcv_mode_3:
  1809. ;receive mode 3 is the only one we support, so we don't have to do anything.
  1810.     ret
  1811.  
  1812.  
  1813.     public    set_multicast_list
  1814. set_multicast_list:
  1815. ;enter with es:di ->list of multicast addresses, cx = number of bytes.
  1816. ;return nc if we set all of them, or cy,dh=error if we didn't.
  1817.     mov    dh,NO_MULTICAST
  1818.     stc
  1819.     ret
  1820.  
  1821.  
  1822.     public    get_multicast_list
  1823. get_multicast_list:
  1824. ;return with nc, es:di ->list of multicast addresses, cx = number of bytes.
  1825. ;return cy, NO_ERROR if we don't remember all of the addresses ourselves.
  1826. ;return cy, NO_MULTICAST if we don't implement multicast.
  1827.     mov    dh,NO_MULTICAST
  1828.     stc
  1829.     ret
  1830.  
  1831.  
  1832.     public    reset_interface
  1833. reset_interface:
  1834. ;reset the interface.
  1835.     assume    ds:code
  1836.     ret
  1837.  
  1838.  
  1839. ;called when we want to determine what to do with a received packet.
  1840. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  1841.     extrn    recv_find: near
  1842.  
  1843. ;called after we have copied the packet into the buffer.
  1844. ;enter with ds:si ->the packet, cx = length of the packet.
  1845.     extrn    recv_copy: near
  1846.  
  1847.     extrn    count_in_err: near
  1848.     extrn    count_out_err: near
  1849.  
  1850.     public    recv
  1851. recv:
  1852. ;called from the recv isr.  All registers have been saved, and ds=cs.
  1853. ;Upon exit, the interrupt will be acknowledged.
  1854.     assume    ds:code
  1855.     ret
  1856.  
  1857.     public    terminate
  1858. terminate:
  1859.     sti
  1860.     call    recv_cancel        ; shut down call-backs
  1861.     cmp    my_open, word ptr 1
  1862.     jne    restore_parms
  1863.     call    dir_close_adapter    ; close out the adapter
  1864. final_exit:
  1865.     ret
  1866.  
  1867. restore_parms:
  1868.     call    dir_restore_open
  1869.     jmp    short final_exit
  1870.  
  1871.     public    recv_exiting
  1872. recv_exiting:
  1873. ;called from the recv isr after interrupts have been acknowledged.
  1874. ;Only ds and ax have been saved.
  1875.     assume    ds:nothing
  1876.     ret
  1877.  
  1878.  
  1879. ;=======================================================================;
  1880. ;============================== RIF Cache ==============================;
  1881. ;=======================================================================;
  1882. ;      The RIF_cache starts here.  Code appearing after the RIF cache   ;
  1883. ;      will be lost after initialization.  It becomes part of the RIF   ;
  1884. ;      cache area, or is released back to DOS.  The program code and    ;
  1885. ;      RIF_cache form a contiguous block in memory.  The first entry    ;
  1886. ;      in the cache is for the broadcast address.  This entry is NEVER  ;
  1887. ;      bumped from the cache!                                           ;
  1888. ;=======================================================================;
  1889.  
  1890. RIF_cache:
  1891.     SA_blk    <0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,82h,0A0h,0>
  1892.  
  1893.  
  1894.  
  1895.     public    usage_msg
  1896. usage_msg    db    CR,LF
  1897.     db    "usage: IBMTOKEN <packet_int_no> <adapter> <RIF_cache>",CR,LF,LF
  1898.     db    "where: packet_int_no     is the interrupt vector",CR,LF
  1899.     db    "       adapter           is adapter 0 or 1",CR,LF
  1900.     db    "       RIF_cache         is number of hosts in RIF cache",CR,LF,CR,LF
  1901.     db    " note: IBM (tm) LAN Support Program or similar DLC",CR,LF
  1902.     db    "       interface for other TR adapters required.",CR,LF,'$'
  1903.  
  1904.     public    copyright_msg
  1905. copyright_msg    db    CR,LF,"Token Ring Driver (3C501 emulation) Version "
  1906.     db    '0'+majver,".",'0'+version,CR,LF
  1907.     IF    alpha NE 0
  1908.     db    "ALPHA TEST VERSION ",'0'+alpha_ver,CR,LF
  1909.     ENDIF
  1910.     db    "portions -",CR,LF
  1911.     db    "Copyright 1989, Queens University",CR,LF
  1912.     db    "Computing and Communications Services",CR,LF
  1913.     db    "Written by Brian Fisher",CR,LF
  1914.     db    "Modified to run with MS LAN Manager/IBM LAN",CR,LF
  1915.     db    "Support Program by Antero Koskinen",CR,LF
  1916.     IF    debug NE 0
  1917.     db    "*** DEBUG VERSION ***",CR,LF
  1918.     ENDIF
  1919.     db    LF,LF
  1920.     db    '$'
  1921.  
  1922.     extrn    set_recv_isr: near
  1923.  
  1924. ;enter with si -> argument string, di -> wword to store.
  1925. ;if there is no number, don't change the number.
  1926.     extrn    get_number: near
  1927.  
  1928.     public    parse_args
  1929. parse_args:
  1930. ;
  1931. ;      si points to next argument of command line...
  1932. ;
  1933.     mov    di,offset token_card    ; next argument is card number
  1934.     call    get_number
  1935.     jc    _parse_exit
  1936.     mov    di,offset SA_size    ; see if cache size ok...
  1937.     call    get_number
  1938. _parse_exit:
  1939.     clc
  1940.     ret
  1941.  
  1942. et_error:
  1943.                     ;    token adapter number out of range
  1944. ;if we got an error,
  1945.     print$    msg_bad_adapter
  1946.     stc
  1947.     ret
  1948.  
  1949. sa_error:
  1950.                     ;    RIF cache allocation problem
  1951. ; if no memory for SA table,
  1952.     print$    no_mem_cache
  1953.     stc
  1954.     ret
  1955.  
  1956. et_init_error:
  1957.     call    dir_close_adapter    ; make sure adapter is closed
  1958.     print$    msg_bad_init
  1959.     stc
  1960.     ret
  1961.  
  1962.     public    etopen
  1963. ;
  1964. ;      Initialize the IBM Token Ring Adapter, determine memory requirements
  1965. ;      for the RIF_cache.
  1966. ;
  1967. etopen:
  1968.     mov    ax,cs
  1969.     mov    ds,ax
  1970.     assume    cs:code, ds:code
  1971.  
  1972.     mov    ax,token_card        ; check card parm for range
  1973.     cmp    ax,1
  1974.     jg    et_error
  1975.     cmp    ax,0
  1976.     jl    et_error        ; less than zero?
  1977.  
  1978.     mov    ax,cs:[SA_size]        ; is the requested RIF cache
  1979.     cmp    ax,SA_min_size        ; size in range?
  1980.     jl    SA_error
  1981.     cmp    ax,SA_max_size
  1982.     jg    SA_error
  1983.  
  1984.     mov    bx,SIZE SA_blk        ; multiply to get bytes needed
  1985.     imul    bx
  1986.     add    ax,(offset RIF_cache)+15; offset + round up value
  1987.     adc    dx,0
  1988.     jne    SA_error        ; dx <> 0, way out of range!
  1989.  
  1990.     mov    cs:[memory_needed],ax    ; bytes needed for code+RIF
  1991.  
  1992. ;      Note: If a memory allocation error occurs when this init routine
  1993. ;      returns, the system will crash because the call backs are already
  1994. ;      defined for LAN Support.  I do a resize here, just to verify that
  1995. ;      it will work.
  1996. ;
  1997.     add    ax,15
  1998.     mov    cl,4
  1999.     shr    ax,cl
  2000.     mov    bx,ax
  2001.     mov    ax,cs            ; get segment
  2002.     mov    es,ax
  2003.     mov    ah,4Ah            ; resize memory block
  2004.     int    21h
  2005.     jc    SA_error        ; c=1, error doing memory
  2006.  
  2007. do_init:
  2008.     call    dir_interrupt        ; check if adapter open
  2009.     cmp    ax, 0            ; adapter open if retcode 0
  2010.     je    modify
  2011.  
  2012.     print$    msg_initialize        ; initialize the adapter
  2013.     call    dir_initialize
  2014.     cmp    ax,0
  2015.     jne    et_init_error
  2016.  
  2017.     print$    msg_opening        ; open the adapter
  2018.     call    dir_open_adapter
  2019.     cmp    ax,0
  2020.     jne    et_init_error
  2021.     mov    my_open, word ptr 1
  2022.     jmp    short no_init
  2023.  
  2024. modify:
  2025.     print$    msg_modifying        ; modify adapter open params
  2026.     call    dir_modify_open
  2027.     cmp    ax, 0
  2028.     je    no_init
  2029.     jmp    et_init_error
  2030.  
  2031. no_init:
  2032.     print$    msg_receiving        ; set up receive routines
  2033.     call    open_receive
  2034.     cmp    ax,0ffh
  2035.     je    init_ok
  2036.     jmp    et_init_error        ; no receive open...
  2037. init_ok:
  2038.  
  2039.     print$    msg_complete        ; card ready to go
  2040.  
  2041.     mov    ax,cs
  2042.     mov    es,ax
  2043.     mov    ds,ax
  2044.  
  2045.     mov    di,offset Token_address
  2046.     mov    cx,EADDR_LEN
  2047.     call    get_address
  2048.  
  2049.     mov    dx,memory_needed    ;tell caller how much memory I want...
  2050.     clc
  2051.     ret
  2052.  
  2053.     public    print_parameters
  2054. print_parameters:
  2055.     ret
  2056.  
  2057. code    ends
  2058.     end
  2059.  
  2060. ;******************************************************************************
  2061. ;
  2062. ;*     End of file: IBMTOKEN.ASM                                              *
  2063. ;
  2064. ;******************************************************************************
  2065.